import json
from typing import Dict, List, Any, Optional
from dataclasses import dataclass
from pathlib import Path
import logging
from datetime import datetime
from enum import Enum
from knowledge_graph import JobKnowledgeGraph
from agents.resume_parser import ResumeParser
from agents.interview_assistant import InterviewAssistant

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger("RecruitmentPortal")

class JobStatus(Enum):
    """职位状态枚举"""
    DRAFT = "draft"
    PUBLISHED = "published"
    CLOSED = "closed"

class CandidateStatus(Enum):
    """候选人状态枚举"""
    NEW = "new"
    SCREENED = "screened"
    INTERVIEWED = "interviewed"
    OFFERED = "offered"
    REJECTED = "rejected"

@dataclass
class JobPosting:
    """职位发布数据类"""
    job_id: str
    title: str
    department: str
    description: str
    requirements: List[str]
    status: JobStatus
    created_at: str
    updated_at: str

@dataclass
class Candidate:
    """候选人数据类"""
    candidate_id: str
    name: str
    resume_file: str
    skills: List[str]
    status: CandidateStatus
    applied_jobs: List[str]  # 申请的职位ID列表
    added_at: str

@dataclass
class InterviewSchedule:
    """面试安排数据类"""
    interview_id: str
    candidate_id: str
    job_id: str
    interviewers: List[str]
    scheduled_time: str
    duration: int  # 分钟
    format: str  # onsite/remote
    notes: Optional[str]

class RecruitmentPortal:
    """企业招聘门户"""
    def __init__(self, kg_client: JobKnowledgeGraph):
        self.kg = kg_client
        self.resume_parser = ResumeParser(kg_client)
        self.interview_assistant = InterviewAssistant(kg_client)
        self.data_dir = Path("b/data/recruitment")
        self._init_data_storage()
        
    def _init_data_storage(self):
        """初始化数据存储"""
        self.data_dir.mkdir(parents=True, exist_ok=True)
        
        # 初始化职位存储
        self.jobs_file = self.data_dir / "jobs.json"
        if not self.jobs_file.exists():
            with open(self.jobs_file, "w") as f:
                json.dump([], f)
        
        # 初始化候选人存储
        self.candidates_file = self.data_dir / "candidates.json"
        if not self.candidates_file.exists():
            with open(self.candidates_file, "w") as f:
                json.dump([], f)
        
        # 初始化面试存储
        self.interviews_file = self.data_dir / "interviews.json"
        if not self.interviews_file.exists():
            with open(self.interviews_file, "w") as f:
                json.dump([], f)
                
        logger.info("招聘门户数据存储初始化完成")
    
    def _load_data(self, file_path: Path) -> List[Dict[str, Any]]:
        """加载数据文件"""
        with open(file_path, "r") as f:
            return json.load(f)
    
    def _save_data(self, file_path: Path, data: List[Dict[str, Any]]):
        """保存数据文件"""
        with open(file_path, "w") as f:
            json.dump(data, f, indent=2)
    
    def create_job_posting(self, job_data: Dict[str, Any]) -> JobPosting:
        """创建职位发布"""
        jobs = self._load_data(self.jobs_file)
        
        new_job = JobPosting(
            job_id=f"job_{len(jobs)+1}",
            title=job_data["title"],
            department=job_data.get("department", "General"),
            description=job_data["description"],
            requirements=job_data["requirements"],
            status=JobStatus.DRAFT,
            created_at=datetime.now().isoformat(),
            updated_at=datetime.now().isoformat()
        )
        
        jobs.append(new_job.__dict__)
        self._save_data(self.jobs_file, jobs)
        
        logger.info(f"创建新职位: {new_job.title} (ID: {new_job.job_id})")
        return new_job
    
    def publish_job(self, job_id: str) -> JobPosting:
        """发布职位"""
        jobs = self._load_data(self.jobs_file)
        
        for job in jobs:
            if job["job_id"] == job_id:
                job["status"] = JobStatus.PUBLISHED.value
                job["updated_at"] = datetime.now().isoformat()
                self._save_data(self.jobs_file, jobs)
                
                logger.info(f"已发布职位: {job_id}")
                return JobPosting(**job)
        
        raise ValueError(f"未找到职位: {job_id}")
    
    def add_candidate(self, candidate_data: Dict[str, Any]) -> Candidate:
        """添加候选人"""
        candidates = self._load_data(self.candidates_file)
        
        # 解析简历
        resume_info = self.resume_parser.parse_resume(candidate_data["resume_file"])
        
        new_candidate = Candidate(
            candidate_id=f"cand_{len(candidates)+1}",
            name=candidate_data.get("name", resume_info.get("name", "Anonymous")),
            resume_file=candidate_data["resume_file"],
            skills=resume_info.get("skills", []),
            status=CandidateStatus.NEW,
            applied_jobs=candidate_data.get("applied_jobs", []),
            added_at=datetime.now().isoformat()
        )
        
        candidates.append(new_candidate.__dict__)
        self._save_data(self.candidates_file, candidates)
        
        logger.info(f"添加新候选人: {new_candidate.name} (ID: {new_candidate.candidate_id})")
        return new_candidate
    
    def screen_candidate(self, candidate_id: str, job_id: str) -> Dict[str, Any]:
        """筛选候选人"""
        candidates = self._load_data(self.candidates_file)
        jobs = self._load_data(self.jobs_file)
        
        # 查找候选人和职位
        candidate = next((c for c in candidates if c["candidate_id"] == candidate_id), None)
        job = next((j for j in jobs if j["job_id"] == job_id), None)
        
        if not candidate or not job:
            raise ValueError("未找到候选人或职位")
        
        # 计算匹配度
        match_score = self._calculate_match_score(
            candidate["skills"],
            job["requirements"]
        )
        
        # 更新候选人状态
        candidate["status"] = CandidateStatus.SCREENED.value
        self._save_data(self.candidates_file, candidates)
        
        logger.info(f"已筛选候选人 {candidate_id} 对职位 {job_id} 的匹配度: {match_score:.2f}")
        
        return {
            "candidate_id": candidate_id,
            "job_id": job_id,
            "match_score": match_score,
            "missing_skills": self._find_missing_skills(
                candidate["skills"],
                job["requirements"]
            ),
            "timestamp": datetime.now().isoformat()
        }
    
    def _calculate_match_score(self, candidate_skills: List[str], 
                              job_requirements: List[str]) -> float:
        """计算技能匹配度"""
        if not job_requirements:
            return 0.0
            
        matched = sum(1 for skill in job_requirements if skill in candidate_skills)
        return matched / len(job_requirements)
    
    def _find_missing_skills(self, candidate_skills: List[str],
                           job_requirements: List[str]) -> List[str]:
        """找出缺失技能"""
        return [skill for skill in job_requirements if skill not in candidate_skills]
    
    def schedule_interview(self, schedule_data: Dict[str, Any]) -> InterviewSchedule:
        """安排面试"""
        interviews = self._load_data(self.interviews_file)
        
        new_interview = InterviewSchedule(
            interview_id=f"int_{len(interviews)+1}",
            candidate_id=schedule_data["candidate_id"],
            job_id=schedule_data["job_id"],
            interviewers=schedule_data["interviewers"],
            scheduled_time=schedule_data["scheduled_time"],
            duration=schedule_data.get("duration", 60),
            format=schedule_data.get("format", "remote"),
            notes=schedule_data.get("notes")
        )
        
        interviews.append(new_interview.__dict__)
        self._save_data(self.interviews_file, interviews)
        
        # 生成面试问题
        job = self.get_job_posting(schedule_data["job_id"])
        questions = self.interview_assistant.generate_interview(
            job.title, difficulty="medium"
        )
        
        logger.info(f"已安排面试: {new_interview.interview_id}")
        return new_interview, questions
    
    def get_job_posting(self, job_id: str) -> JobPosting:
        """获取职位信息"""
        jobs = self._load_data(self.jobs_file)
        job = next((j for j in jobs if j["job_id"] == job_id), None)
        if job:
            return JobPosting(**job)
        raise ValueError(f"未找到职位: {job_id}")
    
    def get_candidate(self, candidate_id: str) -> Candidate:
        """获取候选人信息"""
        candidates = self._load_data(self.candidates_file)
        candidate = next((c for c in candidates if c["candidate_id"] == candidate_id), None)
        if candidate:
            return Candidate(**candidate)
        raise ValueError(f"未找到候选人: {candidate_id}")
    
    def search_candidates(self, skills: List[str], 
                         min_match: float = 0.5) -> List[Dict[str, Any]]:
        """搜索候选人"""
        candidates = self._load_data(self.candidates_file)
        jobs = self._load_data(self.jobs_file)
        
        results = []
        for candidate in candidates:
            match_score = self._calculate_match_score(candidate["skills"], skills)
            if match_score >= min_match:
                candidate_data = {
                    "candidate_id": candidate["candidate_id"],
                    "name": candidate["name"],
                    "match_score": match_score,
                    "status": candidate["status"],
                    "applied_jobs": [
                        self.get_job_posting(job_id).title 
                        for job_id in candidate["applied_jobs"]
                    ]
                }
                results.append(candidate_data)
        
        # 按匹配度排序
        return sorted(results, key=lambda x: x["match_score"], reverse=True)

if __name__ == "__main__":
    # 示例使用
    kg = JobKnowledgeGraph()
    portal = RecruitmentPortal(kg)
    
    # 创建测试职位
    job = portal.create_job_posting({
        "title": "Senior Python Developer",
        "description": "负责核心系统开发...",
        "requirements": ["Python", "Django", "AWS"]
    })
    portal.publish_job(job.job_id)
    
    # 添加候选人
    candidate = portal.add_candidate({
        "resume_file": "b/data/resumes/candidate1.pdf",
        "applied_jobs": [job.job_id]
    })
    
    # 筛选候选人
    screening_result = portal.screen_candidate(candidate.candidate_id, job.job_id)
    print(f"\n筛选结果: 匹配度 {screening_result['match_score']:.0%}")
    print(f"缺失技能: {', '.join(screening_result['missing_skills'])}")
    
    # 安排面试
    interview, questions = portal.schedule_interview({
        "candidate_id": candidate.candidate_id,
        "job_id": job.job_id,
        "interviewers": ["hr1@company.com", "tech1@company.com"],
        "scheduled_time": "2023-12-15T14:00:00"
    })
    
    print(f"\n已安排面试: {interview.interview_id}")
    print(f"面试问题示例: {questions[0].question_text}")